/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.com.ucb.game8numbers.service;

import br.com.ucb.game8numbers.bean.Point;
import br.com.ucb.game8numbers.service.operator.DownOperator;
import br.com.ucb.game8numbers.service.operator.LeftOperator;
import br.com.ucb.game8numbers.service.operator.Operator;
import br.com.ucb.game8numbers.service.operator.RightOperator;
import br.com.ucb.game8numbers.service.operator.UpOperator;
import br.com.ucb.game8numbers.util.Utils;
import br.com.ucb.game8numbers.service.win.WinGame;
import br.com.ucb.game8numbers.tree.PuzzleStateTree;
import br.com.ucb.game8numbers.tree.PuzzleStateTreeNode;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author robs
 */
public class ServiceResolver {

    private DataResponsible fornecedor;
    private Thread treadMovePeca;
    
    public ServiceResolver(DataResponsible fd) {
        this.fornecedor=fd;
    }

    public void resolverPuzzle() {
       treadMovePeca = new Thread(new Runnable(){
            @Override
            public void run() {
                while(!WinGame.ganhei(fornecedor))
                {
                    PuzzleStateTree tree = new PuzzleStateTree();
                    if(tree.getRoot() == null)
                    {
                        PuzzleStateTreeNode node = new PuzzleStateTreeNode();
                        node.setState(fornecedor.getValues());
                        tree.setRoot(node);
                    }
                    fillTreeWithPossibleJOGADAS(tree.getRoot(), fornecedor.getValues());
                }
                Utils.notifyEndGame(fornecedor);
            }

        });
        treadMovePeca.start();
    }
    
    private void fillTreeWithPossibleJOGADAS(PuzzleStateTreeNode node, String[][] state) {
        Point emptyPoint = Utils.getEmptyPoint(state);

        realizeOperation(new UpOperator(), node, emptyPoint, state);
        realizeOperation(new DownOperator(), node, emptyPoint, state);
        realizeOperation(new LeftOperator(), node, emptyPoint, state);
        realizeOperation(new RightOperator(), node, emptyPoint, state);
    }

    private PuzzleStateTreeNode realizeOperation(Operator operator, PuzzleStateTreeNode parent, Point emptyPoint, String[][] state)
    {
        operator.setSource(emptyPoint);
        operator.setState(state);
        String[][] newState = operator.realizeOperation();
        if(newState != null)
        {
            PuzzleStateTreeNode newNode = new PuzzleStateTreeNode();
            newNode.setOperator(operator);
            newNode.setParent(parent);
            newNode.setState(newState);
            if(Utils.getQuantityValuesOutOfPlace(newState) > 0)
            {
                fillTreeWithPossibleJOGADAS(newNode, newState);
            }
            return newNode;
        }
        return null;
    }

    public void stopResolvePuzzle(){
        // o método interrupt não é chamado devido a exeception lancada por causa do
        // método sleep ser interrompido e não a tread que move as peças.
       treadMovePeca.stop();
    }

}
